/**
 * @class Workspace
 * @constructor
 */

var Workspace = Class.create({

    initialize: function() {
        var me = this;
        this.canvas = new Element('div', {'id' : 'canvas'});
        this.workArea = new Element('div', {'id' : 'work-area'}).update(this.canvas);
        $('body').update(this.workArea);
        var screenDimensions = document.viewport.getDimensions();
        this.generateTopMenu();
        this.width = screenDimensions.width;
        this.height = screenDimensions.height - this.canvas.cumulativeOffset().top - 4;
        this._paper = Raphael("canvas",this.width, this.height);
        this.viewBoxX = 0;
        this.viewBoxY = 0;
        this.zoomCoefficient = 1;

        this.background = this.getPaper().rect(0,0, this.width, this.height).attr({fill: 'blue', stroke: 'none', opacity: 0}).toBack();
        this.background.node.setAttribute("class", "panning-background");

        this.adjustSizeToScreen = this.adjustSizeToScreen.bind(this);
        Event.observe (window, 'resize', me.adjustSizeToScreen);
        this.generateViewControls();

        //Initialize pan by dragging
        var start = function() {
            if (editor.isAnyMenuVisible()) {
                return;
            }
            me.background.ox = me.background.attr("x");
            me.background.oy = me.background.attr("y");
            me.background.attr({cursor: 'move'});
        };
        var move = function(dx, dy) {
            var deltax = me.viewBoxX - dx/me.zoomCoefficient;
            var deltay = me.viewBoxY - dy/me.zoomCoefficient;

            me.getPaper().setViewBox(deltax, deltay, me.width/me.zoomCoefficient, me.height/me.zoomCoefficient);
            me.background.ox = deltax;
            me.background.oy = deltay;
            me.background.attr({x: deltax, y: deltay });
        };
        var end = function() {
            me.viewBoxX = me.background.ox;
            me.viewBoxY = me.background.oy;
            me.background.attr({cursor: 'default'});
        };
        me.background.drag(move, start, end);


    },
    
    getSVGCopy: function(anonymizeSettings) {
            editor.getView().unmarkAll();
            var image = $('canvas');
            var background = image.getElementsByClassName('panning-background')[0];
            if(background){
            		background.style.display = "none";
            }
            editor.getView().setAnonymizeStatus(anonymizeSettings);
             //近亲，调解出现样式跳行问题chen.yuguo start
            var exportFamilyData =PedigreeExport.exportAsSimpleJSON(editor.getGraph().DG, "all");
            jsonStr = JSON.parse( exportFamilyData );
            jQuery.each(jsonStr,function (index, item) {//console.log(item);return false;
                //名字
                firstName = item.firstName;
                if(firstName!=undefined){
                    if(firstName!==''){
                        editor.getView().getNode(item.id).getGraphics().updateNameLabel();
                    }
                }
                //结果评估
                evaluatedinfo = item.evaluatedinfo;
                if(evaluatedinfo!=undefined){
                    if(evaluatedinfo!==''){
                        editor.getView().getNode(item.id).getGraphics().updateEvaluatedInfoLabel();
                    }
                }
                //备注
                comments = item.comments;
                if(comments!=undefined){
                    if(comments!==''){
                        editor.getView().getNode(item.id).getGraphics().updateCommentsLabel();
                    }
                }
                //癌症：cancerTypes
                cancerTypes = item.cancerTypes;
                if(cancerTypes!=undefined){
                    editor.getView().getNode(item.id).getGraphics().updateDisorderShapes();
                    editor.getView().getNode(item.id).getGraphics().updateCancerNameLabel();  
                }
            });
             //近亲，调解出现样式跳行问题chen.yuguo end
            var backgroundEl = $('white-bbox-background');
            if (backgroundEl && backgroundEl.parentNode && backgroundEl.previousElementSibling) {
                backgroundEl.parentNode.insertBefore(backgroundEl, backgroundEl.parentNode.firstChild);
            }
            var _bbox = image.down().getBBox();
            var bbox = {};
            bbox.x      = Math.floor(_bbox.x) - 2;
            bbox.y      = Math.floor(_bbox.y) - 2;
            bbox.width  = Math.ceil(_bbox.width)  + 4;
            bbox.height = Math.ceil(_bbox.height) + 4;
            var svgText = image.innerHTML.replace(/xmlns(:xlink)?=".*?"/g, '').replace(/width=".*?"/, '').replace(/height=".*?"/, '')
                          .replace(/viewBox=".*?"/, "viewBox=\"" + bbox.x + " " + bbox.y + " " + bbox.width + " " + bbox.height + "\" width=\"" + (bbox.width) + "\" height=\"" + (bbox.height) +
                          "\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" xmlns=\"http://www.w3.org/2000/svg\"");

            editor.getView().setAnonymizeStatus({});
            svgText = svgText.replace(/(<svg[^<>]+style=")/g, "$1display:block; ");
            svgText = svgText.replace(/<[^<>]+display: ?none;[^<>]*([^/]><\/\w+|\/)>/g, "");
            svgText = svgText.replace(/<text[^<>]+?class="hidden"[^<>]*>(.*?)<\/text>/g, "");
            svgText = svgText.replace(/<[^<>]+[" ]opacity: ?0;[^<>]*([^/]><\/\w+|\/)>/g, "");
            svgText = svgText.replace(/<circle [^<>]+?pedigree-partnership-circle[^<>]*([^/]><\/\w+|\/)>/g, "");
            svgText = svgText.replace(/<a [^<>]*?xlink:title=[^<>]*([^/]><\/\w+|\/)>/g, "");
            svgText = svgText.replace(/<[^<>]+?pedigree-hoverbox[^<>]*([^/]><\/\w+|\/)>/g, "");
            svgText = svgText.replace(/<[^<>]+?pedigree-node-shadow[^<>]*([^/]><\/\w+|\/)>/g, "");
            svgText = svgText.replace(/<linearGradient.*<\/linearGradient>/g, "");
            svgText = svgText.replace(/<radialGradient.*?<\/radialGradient>/g, "");
            svgText = svgText.replace(/<desc>[^<>]+<\/desc>/g, "");
            svgText = svgText.replace(' xlink=', ' xmlns:xlink=');
            svgText = svgText.replace(/NS\d+:(href|show)/g, 'xlink:$1');
            svgText = svgText.replace(/<[^<>]+?node-arrow-text[^<>]*([^/]>\s*(<tspan(.*?)\/tspan>)\s*<\/\w+|\/)>/g, "");
            svgText = svgText.replace(/<[^<>]+?node-arrow-type-C[^<>]*([^/]><\/\w+|\/)>/g, "");
			if(background){
            		background.style.display = "";
            }
            return new SVGWrapper(svgText, bbox, 1.0);
        },

    /**
     *
     * @method getPaper
     * @return {Object} 
     */
    getPaper: function() {
        return this._paper;
    },

    /**
     *
     * @method getWorkArea
     * @return {HTMLElement}
     */
    getWorkArea: function() {
        return this.workArea;
    },

    /**
     *
     * @method getWidth
     * @return {Number}
     */
    getWidth: function() {
        return this.width;
    },

    /**
     *
     * @method getHeight
     * @return {Number}
     */
    getHeight: function() {
        return this.height;
    },

    /**
     *
     * @method generateTopMenu
     */
    generateTopMenu: function() {
        var menu = new Element('div', {'id' : 'editor-menu'});
        this.getWorkArea().insert({before : menu});
        var submenus = [];

        if (editor.isUnsupportedBrowser()) {
            submenus = [{
                name : 'input',
                items: [
                    { key : 'readonlymessage', label : '浏览器不支持模式', icon : 'exclamation-triangle'}
                ]
              }, {
                name : 'output',
                items: [
                    { key : 'export',    label : '导出', icon : 'download'},
                ]
            }];
        } else {
            submenus = [{
                name : 'family',
                items: [
                    { key : 'family', label : '家树图绘制'}
                ]
              }, {
                name : 'output',
                items: [
                    // { key : 'syndrome-rate',    label : '计算携带突变概率', icon : 'random'},
                    { key : 'export',    label : '导出', icon : 'download'},
                    { key : 'save',      label : '保存', icon : 'check'},  
                    // { key : 'test',      label : '测试排序', icon : 'check'},                    
                ]
            },{
                name : 'reset',
                items: [
                    { key : 'viewLegend',  label : ' 查看图例', icon : 'area-chart'},
                ]
            },{
                name : 'edit',
                items: [
                    // { key : 'exportImg',   label : '导出图片', icon : 'undo'},
                    { key : 'undo',   label : '前一步', icon : 'undo'},
                    { key : 'redo',   label : '后一步', icon : 'repeat'},
                    { key : 'layout', label : '自动布局', icon : 'sitemap'},
                ]
            }];
        }
        var _createSubmenu = function(data) {
            var submenu = new Element('div', {'class' : data.name + '-actions action-group'});
            menu.insert(submenu);
            data.items.each(function (item) {
                submenu.insert(_createMenuItem(item));
            });
        };
        var _createMenuItem = function(data) {
            var mi = new Element('span', {'id' : 'action-' + data.key, 'class' : 'menu-item ' + data.key}).insert(new Element('span', {'class' : 'fa fa-' + data.icon})).insert(' ').insert(data.label);
            if (data.callback && typeof(this[data.callback]) == 'function') {
                mi.observe('click', function() {
                    this[data.callback]();
                });
            }
            return mi;
        };
        submenus.each(_createSubmenu);
    },

    /**
     *
     * @method zoom
     * @param {Number} 
     */
    zoom: function(zoomCoefficient) {
        if (zoomCoefficient < 0.15) zoomCoefficient = 0.15;
        if (zoomCoefficient > 0.15 && zoomCoefficient < 0.25) zoomCoefficient = 0.25;
        zoomCoefficient = Math.round(zoomCoefficient/0.05)/20;
        var newWidth  = this.width/zoomCoefficient;
        var newHeight = this.height/zoomCoefficient;
        this.viewBoxX = this.viewBoxX + (this.width/this.zoomCoefficient - newWidth)/2;
        this.viewBoxY = this.viewBoxY + (this.height/this.zoomCoefficient - newHeight)/2;
        this.getPaper().setViewBox(this.viewBoxX, this.viewBoxY, newWidth, newHeight);
        this.zoomCoefficient = zoomCoefficient;
        this.background.attr({x: this.viewBoxX, y: this.viewBoxY, width: newWidth, height: newHeight});
    },

    /**
     *
     * @method generateViewControls
     */
    generateViewControls : function() {
        var _this = this;
        this.__controls = new Element('div', {'class' : 'view-controls'});
        this.__pan = new Element('div', {'class' : 'view-controls-pan', title : 'Pan'});
        this.__controls.insert(this.__pan);
        ['up', 'right', 'down', 'left', 'home'].each(function (direction) {
            var faIconClass = (direction == 'home') ? "fa-user" : "fa-arrow-" + direction;
            _this.__pan[direction] = new Element('span', {'class' : 'view-control-pan pan-' + direction + ' fa fa-fw ' + faIconClass, 'title' : 'Pan ' + direction});
            _this.__pan.insert(_this.__pan[direction]);
            _this.__pan[direction].observe('click', function(event) {
                if (direction == 'home') {
                    _this.centerAroundNode(0);
                }
                else if(direction == 'up') {
                    _this.panTo(_this.viewBoxX, _this.viewBoxY - 300);
                }
                else if(direction == 'down') {
                    _this.panTo(_this.viewBoxX, _this.viewBoxY + 300);
                }
                else if(direction == 'left') {
                    _this.panTo(_this.viewBoxX - 300, _this.viewBoxY);
                }
                else {
                    _this.panTo(_this.viewBoxX + 300, _this.viewBoxY);
                }
            })
        });
        var trackLength = 300;
        this.__zoom = new Element('div', {'class' : 'view-controls-zoom', title : 'Zoom'});
        this.__controls.insert(this.__zoom);
        this.__zoom.track  = new Element('div', {'class' : 'zoom-track'});
        this.__zoom.handle = new Element('div', {'class' : 'zoom-handle', title : '拖动缩放'});
        this.__zoom['in']  = new Element('div', {'class' : 'zoom-button zoom-in fa fa-fw fa-search-plus', title : 'Zoom in'});
        this.__zoom['out'] = new Element('div', {'class' : 'zoom-button zoom-out fa fa-fw fa-search-minus', title : 'Zoom out'});
        this.__zoom.label  = new Element('div', {'class' : 'zoom-crt-value'});
        this.__zoom.insert(this.__zoom['in']);
        this.__zoom.insert(this.__zoom.track);
        this.__zoom.track.insert(this.__zoom.handle);
        this.__zoom.track.style.height = trackLength + 'px';
        this.__zoom.insert(this.__zoom.out);
        this.__zoom.insert(this.__zoom.label);
        this.zoomSlider = new Control.Slider(this.__zoom.handle, this.__zoom.track, {
            axis:'vertical',
            minimum: 0,
            maximum: trackLength,
            increment : 1,
            alignY: 6,
            onSlide : function (value) {
                if (value <= 0.9) {
                    _this.zoom(-value/0.9 + 1.25);
                } else {
                    _this.zoom(0.15);
                }
            },
            onChange : function (value) {
                if (value <= 0.9) {
                    _this.zoom(-value/0.9 + 1.25);
                } else {
                    _this.zoom(0.15);
                }
            }
        });
        if (editor.isUnsupportedBrowser()) {
            this.zoomSlider.setValue(0.5 * 0.9); 
        } else {
           this.zoomSlider.setValue(0.8 * 0.9); //(0.5,0.9) 
        }
        this.__zoom['in'].observe('click', function(event) {
            if (_this.zoomCoefficient < 0.25)
                _this.zoomSlider.setValue(0.9);   
            else
                _this.zoomSlider.setValue(-(_this.zoomCoefficient - 1)*0.9);     // +0.25x
        });
        this.__zoom['out'].observe('click', function(event) {
            if (_this.zoomCoefficient <= 0.25)
                _this.zoomSlider.setValue(1);     
            else
                _this.zoomSlider.setValue(-(_this.zoomCoefficient - 1.5)*0.9);   // -0.25x
        });
        this.__geneticRiskReport = new Element('div', {'class' : 'view-controls-riskreport', title : ''});
        this.__controls.insert(this.__geneticRiskReport);
        this.__grbButton = new Element('input', {type: 'button', name : 'viewriskreport', 'value': '遗传风险评估', 'class' : 'button', 'id': 'viewriskreport_button'});
        this.__geneticRiskReport.insert(this.__grbButton);
        this.getWorkArea().insert(this.__controls);
    },

    getSizeNormalizedToDefaultZoom: function(pixelSizeAtDefaultZoom) {
        return pixelSizeAtDefaultZoom;
    },

    getCurrentZoomLevel: function(pixelSizeAtDefaultZoom) {
        return this.zoomCoefficient;
    },

    /**
     *
     * @method canvasToDiv
     * @param {Number} canvasX 
     * @param {Number} canvasY 
     * @return {{x: number, y: number}} 
     */
    canvasToDiv: function(canvasX,canvasY) {
        return {
            x: this.zoomCoefficient * (canvasX - this.viewBoxX),
            y: this.zoomCoefficient * (canvasY - this.viewBoxY)
        }
    },

    /**
     *
     * @method divToCanvas
     * @param {Number} divX 
     * @param {Number} divY 
     * @return {{x: number, y: number}} 
     */
    divToCanvas: function(divX,divY) {
        return {
            x: divX/this.zoomCoefficient + this.viewBoxX,
            y: divY/this.zoomCoefficient + this.viewBoxY
        }
    },

    /**
     *
     * @method viewportToDiv
     * @param {Number} absX 
     * @param {Number} absY 
     * @return {{x: number, y: number}} 
     */
    viewportToDiv : function (absX, absY) {
        return {
            x : + absX - this.canvas.cumulativeOffset().left,
            y : absY - this.canvas.cumulativeOffset().top
        };
    },

    /**
     *
     * @method panTo
     * @param {Number} x 
     * @param {Number} y 
     */
    panTo: function(x, y, instant) {
        var me = this,
            oX = this.viewBoxX,
            oY = this.viewBoxY,
            xDisplacement = x - oX,
            yDisplacement = y - oY;

        if (editor.isUnsupportedBrowser()) {
            instant = true;
        }

        var numSeconds = instant ? 0 : .4;
        var frames     = instant ? 1 : 11;

        var xStep = xDisplacement/frames,
            yStep = yDisplacement/frames;

        if (xStep == 0 && yStep == 0) return;

        var progress = 0;

        (function draw() {
            setTimeout(function() {
                if(progress++ < frames) {
                    me.viewBoxX += xStep;
                    me.viewBoxY += yStep;
                    me.getPaper().setViewBox(me.viewBoxX, me.viewBoxY, me.width/me.zoomCoefficient, me.height/me.zoomCoefficient);
                    me.background.attr({x: me.viewBoxX, y: me.viewBoxY });
                    draw();
                }
            }, 1000 * numSeconds / frames);
        })();
    },

    /**
     *
     * @method panTo
     * @param {Number} deltaX 
     */
    panByX: function(deltaX, instant) {
        this.panTo(this.viewBoxX + Math.floor(deltaX/this.zoomCoefficient), this.viewBoxY, instant);
    },

    /**
     *
     * @method adjustSizeToScreen
     */
    adjustSizeToScreen : function() {
        var screenDimensions = document.viewport.getDimensions();
        this.width = screenDimensions.width;
        this.height = screenDimensions.height - this.canvas.cumulativeOffset().top - 4;
        this.getPaper().setSize(this.width, this.height);
        this.getPaper().setViewBox(this.viewBoxX, this.viewBoxY, this.width/this.zoomCoefficient, this.height/this.zoomCoefficient);
        this.background && this.background.attr({"width": this.width, "height": this.height});
        if (editor.getNodeMenu()) {
            editor.getNodeMenu().reposition();
        }
    },
    resetPaper(){
        var screenDimensions = document.viewport.getDimensions();
        this.width = screenDimensions.width;
        this.height = screenDimensions.height - this.canvas.cumulativeOffset().top - 4;
        this.getPaper().setSize(this.width, this.height);
    },
    /**
     *
     * @method centerAroundNode
     * @param {Number} nodeID 
     */
    centerAroundNode: function(nodeID, instant, xCenterShift, yCenterShift) {
        var node = editor.getNode(nodeID);
        if(node) {
            var x = node.getX(),
                y = node.getY();
            if (!xCenterShift) xCenterShift = 0;
            if (!yCenterShift) yCenterShift = 0;
            var xOffset = this.getWidth()/this.zoomCoefficient;
            var yOffset = this.getHeight()/this.zoomCoefficient + 400;
            this.panTo(x - xOffset/2 - xCenterShift, y - yOffset/2 - yCenterShift, instant);
        }
    }
});
